﻿using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain.Entity;
using Casamiel.Domain.Response;
using Enyim.Caching;
using MediatR;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Casamiel.Application.Commands.Store
{
    public sealed  class GetAllStoreByStoreNameCommandHandler :IRequestHandler<GetAllStoreByStoreNameCommand, PagingResultRsp<List<StoreEntity>>>
    {
        private readonly IStoreService _storeService;
        
        private readonly IHttpClientFactory _clientFactory;
		private readonly IMemcachedClient _memcachedClient;
		private readonly string _memcachedPre;
		private readonly AMapConfig _aMapConfig;
        public GetAllStoreByStoreNameCommandHandler(IMemcachedClient memcachedClient,IStoreService mbrStoreRepository, IHttpClientFactory httpClientFactory, IOptionsSnapshot<AMapConfig> settings, IOptionsSnapshot<CasamielSettings> snapshot)
        {
			if (snapshot is null) {
				throw new ArgumentNullException(nameof(snapshot));
			}

			_storeService = mbrStoreRepository;
            _clientFactory = httpClientFactory;
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            _aMapConfig = settings.Value;
			_memcachedPre = snapshot.Value.MemcachedPre;
			_memcachedClient = memcachedClient;
        }
      
        public async Task<PagingResultRsp<List<StoreEntity>>> Handle(GetAllStoreByStoreNameCommand request, CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
            var list = await _storeService.GetStoreByNameAsync<ICasaMielSession>(request.storeName).ConfigureAwait(false);
			list = list.Where(c => c.IsCakeShopClose == 0).ToList();
            if (request.lat <= 0)
            {
                list.ForEach(x => x.Distance = 0);
            }
            else
            {
                int _count = list.Count;
                for (int i = 0; i <_count; i++)
                {
                    list[i].IsSend = false;
                    list[i].Distance = DistanceHelper.GetDistance(request.lat, request.lng, list[i].Latitude, list[i].Longitude);// _commonService.MapService.GetGistance(a, new Map { lat=item.Latitude.ToDouble(0), lng=item.Longitude.ToDouble(0)});
                    if (list[i].IsCakeClose == 0 && list[i].IsCakeShopClose==0)
                    {
                        list[i].IsClose = 0;
                    }
                    else
                    {
                        list[i].IsClose = 1;
                    }
                    var distributionRadius = list[i].DistributionRadius.ToString(CultureInfo.CreateSpecificCulture("en-US")).ToDouble(0);
                    if (list[i].Distance <= distributionRadius / 1000)
                    {
                        if (list[i].IsOpenSend > 0)
                        {
                            var _distance = await GetDistance(request.lng, request.lat, list[i].Longitude, list[i].Latitude).ConfigureAwait(false);
                            if (_distance <= distributionRadius)
                            {
                                list[i].IsSend = true;
                            }
                        }
                    }
                }
            }
            //foreach (var item in list)
            //{
            //    if (request.lat <= 0)
            //    {
            //        item.Distance = 0;
            //    }
            //    else
            //    {
            //        item.IsSend = false;
            //        item.Distance = DistanceHelper.GetDistance(request.lat, request.lng, item.Latitude, item.Longitude);// _commonService.MapService.GetGistance(a, new Map { lat=item.Latitude.ToDouble(0), lng=item.Longitude.ToDouble(0)});

            //        var distributionRadius = item.DistributionRadius.ToString().ToDouble(0);
            //        if (item.Distance <= distributionRadius / 1000)
            //        {
            //            if (item.IsOpenSend > 0)
            //            {
            //                var _distance = await GetDistance(request.lng, request.lat, item.Longitude, item.Latitude);
            //                if (_distance <= distributionRadius)
            //                {
            //                    item.IsSend = true;
            //                }
            //            }
            //        }
            //    }
                
            //}
            int pageindex = request.pageIndex;
            if (pageindex <= 0)
            {
                pageindex = 1;
            }
            int pagesize = request.pageSize;
            if (pagesize <= 0)
            {
                pagesize = 10;
            }
            var entity = list.OrderBy(p => p.Distance).ToList().Skip((pageindex - 1) * pagesize).Take(pagesize);
            //var query = entity.Skip((pageindex-1) * pagesize).Take(pagesize);
            //var result = new { code = 0, pageindex, pagesize, total = list.Count, content = entity };

            return new PagingResultRsp<List<StoreEntity>>(entity.ToList(), pageindex, pagesize, list.Count, 0, "");
        }

        private async Task<double> GetDistance(double originLng, double originLat, double soriginLng, double soriginLat)
        {
			var cachekey = $"{_memcachedPre}Dist{originLng.ToString("#0.000000")}-{originLat.ToString("#0.000000")}-{soriginLng.ToString("#0.000000")}-{soriginLat.ToString("#0.000000")}";
			var ddd = await _memcachedClient.GetValueAsync<double>(cachekey).ConfigureAwait(false);
			if (ddd > 0) {
				return ddd;
			}
			var tUrl = $"{_aMapConfig.ApiUrl}/v4/direction/bicycling?origin={originLng},{originLat}&destination={soriginLng},{soriginLat}&key={_aMapConfig.ApiKey}";
            var client = _clientFactory.CreateClient("");
            using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, tUrl))
            {
                using (var response = await client.SendAsync(requestMessage).ConfigureAwait(false))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                        var json = JsonConvert.DeserializeObject<JObject>(result);
                        if (json["errcode"].ToString() == "0")
                        {
                            string distance = json["data"]["paths"][0]["distance"].ToString();
							await _memcachedClient.AddAsync(cachekey, distance.ToDouble(0), 7200).ConfigureAwait(false);

							return distance.ToDouble(0);
                        }
                    }
                }
            }


              
            return 0;
        }
    }
}
